-- Base simulator
require"project"

-- set aliases and key words
require"core.def.alias"   
require"core.def.keyword"
require"core.def.association"
require"core.def.prototype"
require"core.def.decorator"
require"core.def.state"
require"core.def.action"

-- Base node topography
root     = createnode("root")
actors   = createnode("actorroot")
players  = createnode("playerroot")
npcs     = createnode("npcroot")

association.add(root,owner_link,actors)

--[[
-- Basic project data
_project = {}
_project.path = "./"
_project.name = "ClassIV-Base"
_project.author = "Robert Gould"
_project.version = 0.1
_project.description = [==[This is a basic project to be used as a starting point for other projects]==]
--]]

-- Common run data
_run = {}

-- Core loop functionality
core = core or {}
core.init = function()
  --What do we need to do here...
end
core.finish = function()
  --What do we need to do here...
end
core.pause = function()
  --What do we need to do here...
end
core.preasync = function(dt)
  --What do we need to do here...
end
core.async = function(dt)
  --What do we need to do here...
end
core.postasync = function(dt)
  --What do we need to do here...
end

--[[
game_env = {
}
--]]
setgameenvironment = function()
--[[
  local ge = {}
  local ge_mt = {
      __index = function(t,k)
        print("!")
        return t.__coreenv[k]-- or t.__coreenv[k] 
      end,
      __newindex = function(t,k,v)
        print("?")
        if t.__coreenv[k] ~= nil then
          error("attempt to overide core name "..tostring(k))          
        else
          --t[k]=v
        end
      end,
  }
  ge.__coreenv = getfenv(2)
  setmetatable (ge,ge_mt)
  setfenv(2,ge)
--]]
end

revertgameenvironment = function()
--[[
  setfenv(2, getfenv(2).__coreenv)
--]]
end
  
-- set aliases and key words
--[[
require"game.def.alias"   
require"game.def.keyword"
require"game.def.association"
require"game.def.prototype"
require"game.def.decorator"
require"game.def.state"
require"game.def.action"
--]]  

-- Load stuff that the simulaion should do
require"game"
game = game or {}
game.init = game.init or function() end
game.preasync = game.preasync or function(dt) end
game.async = game.async or function(dt) end
game.postasync = game.postasync or function(dt) end
game.pause = game.pause or function() end
game.finish = game.finish or function() end

_run.init = function()

end

_run.preasync = function(dt)
  printd("pre")
  core.preasync(dt)
  game.preasync(dt)
end

_run.async    = function(dt)
  printd("doing stuff")
  core.async(dt)
  game.async(dt)    
end

_run.postasync = function(dt)
  printd("post")
  core.postasync(dt)
  game.postasync(dt)    
end

main = function(fps)

  _run.startstamp = now
  _run.framecount = 0
  _run.continue   = true
  _run.pause      = false
  
  core.init()
  setgameenvironment()
  game.init()
    
  _run.init() 
  local start = 0
  local dt    = 0

  printd("simulation has started")
  
  while _run.continue == true do
      start = clock
      --do stuff
      if _run.pause == false then
        --Do things that need to be done synchronously before the asynchronous stage
        _run.preasync(dt)
        --Do things that can be done asynchronously
        _run.async(dt)
        --Do things that need to be done synchronously after the asynchronous stage
        _run.postasync(dt)
      else
        core.pause(dt)
        game.pause(dt)    
      end
      if __BENCHMARK__ then
        if (clock - _run.startclock) > 1 then
          _run.startclock = clock
          printd(_run.framecount.."fps")
          _run.framecount = 0 
        end
        _run.framecount = _run.framecount + 1 
      else -- sleep
        local sleep = (1/fps) - ((clock-start)/1000)
        wait(sleep)
      end
      dt = clock-start
  end
  
  _run.finishstamp = now
  game.finish()
  revertgameenvironment()
  core.finish()
  
  printd("simulation has finished")
    
end


--Use name spaces, because they make flushing for rapid development easier
--Drive application through script pipe, MAx data goes through script to the engine
--Drag and Drop Scripts onto the App
--nomenclature resource instead of tool for actions???
--need to determine who is the main actor for reciprocative verbs such as Buy and Sell 
  
